library ieee;
use ieee.std_logic_1164.all;

library lib_expoRNS;

entity master_unit is
	generic(
		Z : positive range 1 to 256 ;		-- Nombre de bits du module
		
		N_alpha : positive ;	-- Vecteur de base : OBLIGATOIREMENT de la forme 2^n 
		log2Ralpha : positive;		

		N_beta1 : positive ;	-- Vecteur de base : OBLIGATOIREMENT PAS de la forme 2^n 
		R_beta1 : positive ;
		k_beta1 : positive ;
		log2Rbeta1 : positive;		


		N_beta2 : positive ;	-- Vecteur de base : OBLIGATOIREMENT de la forme 2^n 
		R_beta2 : positive ;
		log2Rbeta2 : positive;
		k_beta2 : positive;

		e1 : positive ;       --Coefficiant form TRC (view enwikipedia TRC)
		e2 : positive ;       
		e3 : positive
	) ;
	port (
		a   : in std_logic_vector(Z-1 downto 0) ;                 -- Nombre a exponentier
		p   : in std_logic_vector(Z-1 downto 0) ;   -- Puissance
		clk : in std_logic ;
		reset : in std_logic ;
		start : in std_logic ;
		S   : out std_logic_vector(Z-1 downto 0)
	);  -- Nombre exponentier

end master_unit;

----------------------------------------------------------------------------------------------------

architecture master1  of master_unit is

component k_unit
	generic ( Z : positive range 1 to 256 := Z ) ;
	
	port (
		p : in  std_logic_vector(Z-1 downto 0) ;
		S : out std_logic_vector(Z-1 downto 0)
	) ;
end component;

component exponentiation_unit
	generic (
		Z : positive range 1 to 256 ;
		N : positive ;	-- Vecteur de base utilisé
		R : positive ;       -- Plus proche puissance de 2 de N par valeur supérieure
		log2R : positive;
		k : positive ;	-- Constante nécessaire au calcul
		montgomery : boolean ;
		reel : boolean
	);
	port (
		reset : in std_logic;
		clk : in std_logic;
		bit_utile : in std_logic_vector(Z-1 downto 0);
		a     : in std_logic_vector(Z-1 downto 0);
		p     : in std_logic_vector(Z-1 downto 0);  --Puissance
		start : in std_logic;
                S : out std_logic_vector(Z-1 downto 0)
	);
end component;

component trc_Unit
	generic (
		Z : positive range 1 to 256 := Z ;
		
		--Vecteurs de base
		N_alpha : positive := N_alpha ;
		
		R_beta1 : positive := R_beta1 ;
		log2Rbeta1 : positive := log2Rbeta1 ;
		N_beta1 : positive := N_beta1 ;
		k_beta1 : positive := k_beta1 ;
		
		N_beta2 : positive := N_beta2 ;
		R_beta2 : positive := R_beta2 ;
		log2Rbeta2 : positive := log2Rbeta2 ;
		k_beta2 : positive := k_beta2 ;
		
		e1 : positive := e1 ;       --Coefficiant form TRC (view enwikipedia TRC)
		e2 : positive := e2 ;       
		e3 : positive := e3
	) ;
	port (
		clk	: in std_logic ;
		reset	: in std_logic ;
		in_alpha : in std_logic_vector(Z-1 downto 0) ;
		in_beta1 : in std_logic_vector(Z-1 downto 0) ;
		in_beta2 : in std_logic_vector(Z-1 downto 0) ;
		s  : out std_logic_vector(Z-1 downto 0)    
	);

end component;

component  RNS_Dec_Unit 
	generic(
		Z_RNS : positive range 1 to 256 := Z ;		-- Nombre de bits du module
		
		N_alpha : positive := N_alpha ;	-- Vecteur de base : OBLIGATOIREMENT de la forme 2^n 
		log2N_alpha :positive := log2Ralpha ;
		
		N_beta1 : positive := N_beta1 ;	-- Vecteur de base : OBLIGATOIREMENT PAS de la forme 2^n 
		R_beta1 : positive := R_beta1 ;
		log2R_beta1 :positive := log2Rbeta1 ;
		k_beta1 : positive := k_beta1 ;
		
		N_beta2 : positive := N_beta2 ;	-- Vecteur de base : OBLIGATOIREMENT de la forme 2^n 
		R_beta2 : positive := R_beta2 ;
		log2R_beta2 :positive := log2Rbeta2 ;
		k_beta2 : positive := k_beta2
	) ;
	port(
		a : in std_logic_vector(Z-1 downto 0) ;
		clk : in std_logic ;
		reset : in std_logic ;
		alpha : out std_logic_vector(Z-1 downto 0) ;
		beta1 : out std_logic_vector(Z-1 downto 0) ;
		beta2 : out std_logic_vector(Z-1 downto 0) ;
		start : out std_logic
	);

end component;


	signal I_alpha, I_beta1, I_beta2,  I_bit_utile, I_S1, I_S2, I_S3 : std_logic_vector(Z-1 downto 0) ;
	signal I_start_dec:  std_logic ;

begin
	--Mapage \o/
	
	
	RNS_Dec : RNS_Dec_Unit port map ( a => a, clk => clk, reset => reset, alpha => I_alpha, beta1 => I_beta1, beta2 => I_beta2, start => I_start_dec );
	
	--Les k_unit
	
	k_bit_utile : k_unit port map (p, I_bit_utile);
	
	Expoalpha: exponentiation_unit
		generic map( Z => Z, N => N_alpha, R => N_alpha, log2R => log2Ralpha, k => 1, montgomery => true, reel => true)
		port map ( reset => reset, clk => clk, bit_utile => I_bit_utile, a => I_alpha, p => p, start => I_start_dec, S => I_S1 );
	
	Expobeta1 :  exponentiation_unit
		generic map( Z => Z, N => N_beta1, R => R_beta1, log2R => log2Rbeta1, k => k_beta1, montgomery => true, reel => false)
		port map ( reset => reset, clk => clk, bit_utile => I_bit_utile, a => I_beta1, p => p, start => I_start_dec, S => I_S2 );
	
	Expobeta2 :   exponentiation_unit
		generic map( Z => Z, N => N_beta2, R => R_beta2, log2R => log2Rbeta2, k => k_beta2, montgomery => true, reel => false)
		port map ( reset => reset, clk => clk, bit_utile => I_bit_utile, a => I_beta2 , p => p, start => I_start_dec, S => I_S3 );
	
	TRC : trc_Unit port map( clk => clk, reset => reset, in_alpha => I_S1, in_beta1 => I_S2, in_beta2 => I_S3, S => S );

end master1 ;
